<template>
    <el-dialog
        :model-value="dialogVisible"
        :fullscreen="true"
        :align-center="true"
        @close="cancel"
        @open="open_dialog"
        class="mask__dialog"
        :destroy-on-close="true"
        v-if="dialogVisible"
    >

        <div class="drawing-app">
            <div class="toolbar">
            
            <div class="tool-group">
                <label>画笔颜色:</label>
                <input type="color" v-model="drawColor" @change="updateBrush">
            </div>
            
            <div class="tool-group">
                <label>笔刷大小:</label>
                <input type="range" v-model="brushSize" min="1" max="100" @input="updateBrush">
                <span>{{ brushSize }}px</span>
            </div>
            
            <div class="tool-group">
                <button @click="toggleEraser">{{ isEraser ? '画笔' : '橡皮擦' }}</button>
                <button @click="clearCanvas">清空画布</button>
            </div>
            
            <div class="tool-group">
                <button @click="undo" :disabled="historyIndex <= 0">撤销</button>
                <button @click="redo" :disabled="historyIndex >= drawingHistory.length - 1">重做</button>
            </div>
            
            <div class="tool-group">
                <button @click="saveDrawingOnly">保存绘图</button>
            </div>

            <div class="tool-group">
                <button @click="cancel">关闭</button>
            </div>
            </div>
            
            <div class="maskEditor_hidden" ref="parent_container">

            <div class="maskEditorCanvasContainer" ref="canvas_container">
                <div>
                <img :src="bg_image" alt="" class="image__bg">
                <canvas ref="canvas" class="draw__canvas"></canvas>
                </div>
                
            </div>
            
            </div>
        </div>



    </el-dialog>
</template>
           
<script setup>
    import { ref, onMounted, nextTick, watch, watchEffect, reactive , defineEmits, defineProps } from 'vue'
    import LoadingBox from '@/utils/LoadingBox'

    const props = defineProps(['visible', "bg_image_url", "mask_url"])
    const emit = defineEmits(['cancel', 'confirm'])
    defineExpose({open_dialog, })
    const dialogVisible = ref(props.visible)
    const data_obj = ref({})

    // 图片数据

    const bg_image = ref(null)
    const imageSize = ref({width: 500, height: 400})

    const mask_image = ref(null)

    // 绘制状态
    const isDrawing = ref(false)
    const isDragging = ref(false)
    const lastPos = ref({ x: 0, y: 0 })
    const startDragPos = ref({ x: 0, y: 0 })

    // 画笔设置
    const drawColor = ref('#000000')
    const brushSize = ref(25)
    const isEraser = ref(false)


    // 画布变换
    const transform = ref({
    scale: 1,
    offsetX: 0,
    offsetY: 0
    })
    // 绘制历史
    const drawingHistory = ref([{ drawings: [], transform: { ...transform.value } }])
    const historyIndex = ref(0)
    // 当前绘制路径
    const currentPath = ref({
    color: '',
    size: 0,
    points: [],
    isEraser: false,
    type: 'path'
    })

    // 画布实例
    const parent_container = ref(null)
    const canvas_container = ref(null)
    const canvas = ref(null)
    const ctx = ref(null)


    const initCanvas = ()=>{
    if (!canvas_container.value) return

    // canvas_container.value.style.width = '100px'
    // canvas_container.value.style.height = '100px'

    ctx.value = canvas.value.getContext('2d')
    resizeContain()

    setupEventListeners()
        
    }

    // 获取父盒子的宽高
    const getparentWH = ()=>{
    if (!parent_container.value) return [0, 0]
    return [parent_container.value.clientWidth, parent_container.value.clientHeight]
    }


    // 设置事件监听
    const setupEventListeners = () => {
    console.log('监听canvas')
    const p = parent_container.value
    const c = canvas.value
    c.onmousedown = handleMouseDown
    c.onmousemove = handleMouseMove
    c.onmouseup = handleMouseUp
    c.onmouseleave = handleMouseUp


    p.onwheel = handleWheel
    }

    // 处理滚轮缩放
    const handleWheel = (e) => {
    e.preventDefault()
    
    const rect = parent_container.value.getBoundingClientRect()
    const mouseX = e.clientX - rect.left
    const mouseY = e.clientY - rect.top
    
    // 计算鼠标在画布内容坐标系中的位置
    const canvasX = (mouseX - transform.value.offsetX) / transform.value.scale
    const canvasY = (mouseY - transform.value.offsetY) / transform.value.scale
    
    // 计算缩放因子
    const delta = -e.deltaY
    const zoomFactor = delta > 0 ? 1.1 : 0.9
    
    // 计算新缩放比例 (限制在0.1到10倍之间)
    const newScale = Math.min(Math.max(transform.value.scale * zoomFactor, 0.1), 10)
    
    // 如果缩放比例没有变化，则不做处理
    if (Math.abs(newScale - transform.value.scale) < 0.01) return
    
    // 更新缩放比例
    transform.value.scale = newScale
    
    // 调整偏移量，使鼠标下的点保持不动
    transform.value.offsetX = mouseX - canvasX * transform.value.scale
    transform.value.offsetY = mouseY - canvasY * transform.value.scale
    
    // 重绘画布
    // console.log(transform.value)
    resizeContain()
    redrawCanvas()
    }

    // 获取鼠标在画布坐标系中的位置
    const getCanvasPos = (clientX, clientY) => {
    const rect = canvas_container.value.getBoundingClientRect()
    return {
        x: (clientX - rect.left) / transform.value.scale,
        y: (clientY - rect.top) / transform.value.scale
    }
    }

    // 鼠标按下处理
    const handleMouseDown = (e) => {
    if (e.ctrlKey || e.metaKey || e.button === 1) {
        // 按住Ctrl键或中键开始拖拽
        isDragging.value = true
        startDragPos.value = {
        x: e.clientX,
        y: e.clientY
        }
        canvas.value.style.cursor = 'grabbing'
        return
    }

    // 开始绘制
    isDrawing.value = true
    const pos = getCanvasPos(e.clientX, e.clientY)
    lastPos.value = pos
    
    // 开始新路径
    currentPath.value = {
        color: isEraser.value ? '#000000' : drawColor.value,
        size: brushSize.value,
        points: [pos],
        isEraser: isEraser.value,
        type: 'path'
    }
    }

    // 鼠标移动处理
    const handleMouseMove = (e) => {
    if (isDragging.value) {
        // 处理拖拽
        transform.value.offsetX += e.clientX - startDragPos.value.x
        transform.value.offsetY += e.clientY - startDragPos.value.y
        resizeContain()
        redrawCanvas()
        startDragPos.value = {
        x: e.clientX,
        y: e.clientY
        }
    } else if (isDrawing.value) {
        // 处理绘制
        const pos = getCanvasPos(e.clientX, e.clientY)
        currentPath.value.points.push(pos)
        redrawCanvas()
        lastPos.value = pos
    }
    }

    // 鼠标释放处理
    const handleMouseUp = () => {
    if (isDrawing.value && currentPath.value.points.length > 1) {
        // 完成当前路径并保存到历史
        saveCurrentPathToHistory()
    }
    
    isDrawing.value = false
    isDragging.value = false
    canvas.value.style.cursor = 'crosshair'
    }

    // 保存当前路径到历史
    const saveCurrentPathToHistory = () => {
    // 复制当前历史状态
    const currentState = JSON.parse(JSON.stringify(drawingHistory.value[historyIndex.value]))
    
    // 添加新路径
    currentState.drawings.push({ ...currentPath.value })
    currentState.transform = { ...transform.value }
    
    // 更新历史记录
    drawingHistory.value = drawingHistory.value.slice(0, historyIndex.value + 1)
    drawingHistory.value.push(currentState)
    historyIndex.value++
    
    // 限制历史记录数量
    if (drawingHistory.value.length > 50) {
        drawingHistory.value.shift()
        historyIndex.value--
    }
    }

    // 重绘画布
    const redrawCanvas = () => {
    
    if (!ctx.value || !canvas.value) return
    
    // 清除画布
    ctx.value.clearRect(0, 0, canvas.value.width, canvas.value.height)
    
    // 保存当前状态
    ctx.value.save()
    

    // 绘制图片的蒙版

    if(mask_image.value){

        ctx.value.strokeStyle = currentPath.value.color
        
        ctx.value.drawImage(mask_image.value, 0, 0)

        // 3. 设置合成模式 - 只在非透明区域绘制新颜色
        ctx.value.globalCompositeOperation = 'source-in';
        // 4. 填充新颜色
        ctx.value.fillStyle = currentPath.value.color; // 设置为红色
        ctx.value.fillRect(0, 0, canvas.value.width, canvas.value.height);
        ctx.value.globalCompositeOperation = 'source-over'
    }
    ctx.value.lineCap = 'round'
    ctx.value.imageSmoothingEnabled = true
    
    // 绘制历史记录
    const currentHistory = drawingHistory.value[historyIndex.value]
    currentHistory.drawings.forEach(path => {
        if (path.isEraser) {
        
        ctx.value.globalCompositeOperation = 'destination-out'
        } else {
        ctx.value.globalCompositeOperation = 'source-over'
        ctx.value.strokeStyle = path.color
        }
        
        ctx.value.lineWidth = path.size
        ctx.value.beginPath()
        ctx.value.moveTo(path.points[0].x, path.points[0].y)
        
        for (let i = 1; i < path.points.length; i++) {
        ctx.value.lineTo(path.points[i].x, path.points[i].y)
        }
        
        ctx.value.stroke()
        
        
    })
    
    // 绘制当前路径（如果正在绘制）
    if (isDrawing.value && currentPath.value.points.length > 1) {
        if (currentPath.value.isEraser) {
        ctx.value.globalCompositeOperation = 'destination-out'
        } else {
        ctx.value.globalCompositeOperation = 'source-over'
        ctx.value.strokeStyle = currentPath.value.color
        }
        
        ctx.value.lineWidth = currentPath.value.size
        ctx.value.beginPath()
        ctx.value.moveTo(currentPath.value.points[0].x, currentPath.value.points[0].y)
        
        for (let i = 1; i < currentPath.value.points.length; i++) {
        ctx.value.lineTo(currentPath.value.points[i].x, currentPath.value.points[i].y)
        }
        
        ctx.value.stroke()
    }
    
    // 恢复状态
    ctx.value.restore()
    }


    const resizeContain = ()=>{
        if (!canvas_container.value) return
        canvas_container.value.style.width = (imageSize.value.width * transform.value.scale)+'px'
        canvas_container.value.style.height = (imageSize.value.height * transform.value.scale)+'px'

        canvas_container.value.style.left =  transform.value.offsetX+'px'
        canvas_container.value.style.top = transform.value.offsetY+'px'

        canvas.value.width = imageSize.value.width
        canvas.value.height = imageSize.value.height


    }

    // 橡皮擦
    const toggleEraser = ()=>{
    isEraser.value = ~isEraser.value
    }

    // 撤销操作
    const undo = () => {
    if (historyIndex.value > 0) {
        historyIndex.value--
        redrawCanvas()
    }
    }

    // 重做操作
    const redo = () => {
    if (historyIndex.value < drawingHistory.value.length - 1) {
        historyIndex.value++
        redrawCanvas()
    }
    }

    // 清空画布
    const clearCanvas = () => {
    drawingHistory.value = [{ drawings: [], transform: { ...transform.value } }]
    historyIndex.value = 0
    mask_image.value = null
    redrawCanvas()
    }

    // 保存绘图（仅保存绘制的图形，大小与背景图片一致）
    const saveDrawingOnly = () => {
    if (!canvas.value) return

    const loadingInst = LoadingBox.open(true)
    
    // 创建一个与背景图片大小相同的临时画布
    const tempCanvas = document.createElement('canvas')
    tempCanvas.width = imageSize.value.width
    tempCanvas.height = imageSize.value.height
    const tempCtx = tempCanvas.getContext('2d')
    
    // 应用当前变换状态绘制所有路径
    const currentHistory = drawingHistory.value[historyIndex.value]
    
    tempCtx.lineCap = 'round'

    // 绘制图片的蒙版
    tempCtx.globalCompositeOperation = 'source-over'
    tempCtx.fillStyle = '#000'; // 设置为
    tempCtx.fillRect(0, 0, tempCanvas.width, tempCanvas.height);

    if(mask_image.value){

        // 创建一个与背景图片大小相同的临时画布
        // const tempCanvasMask = document.createElement('canvas')
        // tempCanvasMask.width = imageSize.value.width
        // tempCanvasMask.height = imageSize.value.height
        // const maskTempCtx = tempCanvasMask.getContext('2d')

        //   // 绘制图片的蒙版
        // maskTempCtx.globalCompositeOperation = 'source-over'
        // maskTempCtx.fillStyle = '#000'; // 设置为
        // maskTempCtx.fillRect(0, 0, tempCanvasMask.width, tempCanvasMask.height);
        // 3. 设置合成模式 - 只在非透明区域绘制新颜色
        tempCtx.globalCompositeOperation = 'source-in';
        tempCtx.drawImage(mask_image.value, 0, 0)
        // 4. 填充新颜色
        tempCtx.fillStyle = '#fff'; // 设置为
        tempCtx.fillRect(0, 0, tempCanvas.width, tempCanvas.height);
        tempCtx.globalCompositeOperation = 'source-over'

        // tempCtx.drawImage(tempCanvasMask, 0, 0)
    }

    
    currentHistory.drawings.forEach(path => {
        if (path.isEraser) {
        tempCtx.globalCompositeOperation = 'destination-out'
        } else {
        tempCtx.globalCompositeOperation = 'source-over'
        tempCtx.strokeStyle = '#fff'
        }
        
        tempCtx.lineWidth = path.size
        tempCtx.beginPath()
        tempCtx.moveTo(path.points[0].x, path.points[0].y)
        
        for (let i = 1; i < path.points.length; i++) {
        tempCtx.lineTo(path.points[i].x, path.points[i].y)
        }
        
        tempCtx.stroke()
    })

    // 创建一个与背景图片大小相同的临时画布
    const tempCanvasMask = document.createElement('canvas')
    tempCanvasMask.width = imageSize.value.width
    tempCanvasMask.height = imageSize.value.height
    const maskTempCtx = tempCanvasMask.getContext('2d')
        // 绘制图片的蒙版
    maskTempCtx.globalCompositeOperation = 'source-over'
    maskTempCtx.fillStyle = '#000'; // 设置为
    maskTempCtx.fillRect(0, 0, tempCanvasMask.width, tempCanvasMask.height);

    maskTempCtx.drawImage(tempCanvas, 0, 0)
    
    // // 转换为图片并下载
    const dataURL = tempCanvasMask.toDataURL('image/png')
    // const link = document.createElement('a')
    // link.download = 'drawing-' + new Date().toISOString().slice(0, 10) + '.png'
    // link.href = dataURL
    // link.click()

    emit('confirm', dataURL)

    loadingInst.close()
    emit('cancel')

    }

    // 处理背景图片
    const handBackground = ()=>{


        const img = new Image()
        img.onload = () => {
        bg_image.value = props.bg_image_url
        imageSize.value = {
            width: img.width,
            height: img.height
        }
        var p_size = getparentWH()
        if (img.width >=  img.height){
            transform.value.scale = p_size[0] / img.width

            transform.value.offsetY = (p_size[1] - (img.height * transform.value.scale)) / 2
        }else{
            transform.value.scale = p_size[1] / img.height
            transform.value.offsetX = (p_size[0] - (img.width * transform.value.scale)) / 2
        }
        resizeContain()

        handMaskImage()
        }
        img.src = props.bg_image_url

    }

    // 处理黑白蒙版
    const handMaskImage = async ()=>{

        if (props.mask_url){
            const img = await srcLoadImage(props.mask_url)
            const canvas_mask = document.createElement('canvas');
            const ctx_mask = canvas_mask.getContext('2d');
            canvas_mask.width = img.width;
            canvas_mask.height = img.height;
            ctx_mask.drawImage(img, 0, 0);
            const imageData = ctx_mask.getImageData(0, 0, img.width, img.height);
            const data = imageData.data;
            var rgbData = [];
            for (var i = 0; i < data.length; i += 4) {
                if(data[i]==0){
                rgbData.push(0, 0, 0, 0);
                }else{
                rgbData.push(data[i], data[i+1], data[i+2], data[i]);
                }
            }
            ctx_mask.putImageData(
                        new ImageData(new Uint8ClampedArray(rgbData), img.width),
                        0,
                        0
                        )
            var base64 = canvas_mask.toDataURL("PNG")
            const img1 = await srcLoadImage(base64)
            mask_image.value = img1
            redrawCanvas()
        }

    }

    // 加载图片
    const srcLoadImage = (file_url) => {
    return new Promise((resolve, reject) => {
        const img = new Image()
        img.src = file_url
        img.onload = () => resolve(img)
        img.onerror = reject
    })
    }

    // 加载图片
    const fileLoadImage = (file) => {
    return new Promise((resolve, reject) => {
        const reader = new FileReader()
        reader.onload = (event) => {
        const img = new Image()
        img.onload = () => resolve(img)
        img.onerror = reject
        img.src = event.target.result
        }
        reader.onerror = reject
        reader.readAsDataURL(file)
    })
    }

    watch(() => props.visible, (value) => {
        if (value){
            dialogVisible.value = true
        }else{
            emit('cancel')
            dialogVisible.value = false
        }
        // value && (dialogVisible.value = true)
    })
    watchEffect(() => {
        data_obj.value = props.instance
        
    })

    async function open_dialog() {
        const loadingInst = LoadingBox.open(true)
        initCanvas()
        
        await handBackground()
        loadingInst.close()
        
        
    }


    onMounted(()=>{        
  
    })

    

    function cancel(){
        emit('cancel')
        
    }
    
</script>
<style scoped lang="scss">
.mask__dialog{
    padding: 0;
}
   
   .maskEditor_hidden{
        width: 100%;
        height: calc(100% - 50px);
        display: flex;
        position: relative;
        overflow: hidden;
        .maskEditorCanvasContainer{
            height: 100%;
            width: 100%;
            position: absolute;
            // border: 1px solid red;
            div{
            position: relative;
            width: 100%;
            height: 100%;
            .image__bg{
                position: absolute;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
            }
            .draw__canvas{
                position: absolute;
                top: 0;
                left: 0;
                width: 100%;
            height: 100%;
            }
            }
        }
        }
        .drawing-app {
        display: flex;
        flex-direction: column;
        height: 100%;
        overflow: hidden;
        }
        .toolbar {
        height: 50px;
        padding: 10px;
        background: #f0f0f0;
        display: flex;
        flex-wrap: nowrap;
        gap: 15px;
        align-items: center;
        }

        .tool-group {
        display: flex;
        align-items: center;
        gap: 8px;
        }

        .tool-group label {
        font-weight: bold;
        font-size: 14px;
        }

        button {
        padding: 5px 10px;
        background: #fff;
        border: 1px solid #ccc;
        border-radius: 4px;
        cursor: pointer;
        }

        button:hover {
        background: #e0e0e0;
        }

        button:disabled {
        opacity: 0.5;
        cursor: not-allowed;
        }
</style>


